
#ifndef _Demo_TutorialGameState_H_
#define _Demo_TutorialGameState_H_

#include "OgrePrerequisites.h"
#include "GameState.h"
#include "OgreSceneManager.h"
class RoadMileLine;
class MeshData;
namespace Ogre
{
    namespace v1
    {
        class TextAreaOverlayElement;
    }
	class HlmsPbsDatablock;
}

namespace OgreModel
{
    class GraphicsSystem;
    class CameraController;

    /// Base game state for the tutorials. All it does is show a little text on screen :)
    class GameStateMain : public GameState
    {
    protected:
        GraphicsSystem      *mGraphicsSystem;

        /// Optional, for controlling the camera with WASD and the mouse
        CameraController    *mCameraController;

        Ogre::String        mHelpDescription;
        Ogre::uint16        mDisplayHelpMode;
        Ogre::uint16        mNumDisplayHelpModes;

        Ogre::v1::TextAreaOverlayElement *mDebugText;
        Ogre::v1::TextAreaOverlayElement *mDebugTextShadow;

        virtual void createDebugTextOverlay(void);

        virtual void generateDebugText( float timeSinceLast, Ogre::String &outText );
		
		SharedPointer<RoadMileLine> m_pRoadMileLine;

    public:
        GameStateMain( const Ogre::String &helpDescription );
        
		virtual ~GameStateMain();

		void BindRoadMileLine(SharedPointer<RoadMileLine> pMile);

        void _notifyGraphicsSystem( GraphicsSystem *graphicsSystem );

        virtual void createScene01(void);

        virtual void update( float timeSinceLast );
#if OGRE_USE_SDL2
		virtual void keyPressed(const SDL_KeyboardEvent &arg);
		virtual void keyReleased(const SDL_KeyboardEvent &arg);
		virtual void mouseMoved(const SDL_Event &arg);
#else
		virtual void VKMouseState(const std::map<int, bool> & vk_Key) ;
		virtual void VKkeyboardState(const std::map<int, bool> & vk_Key) ;
#endif
		void ChangeObjMaterial(const ZMVector<ZMString>& vObj, const ZMString& materialName);

		Ogre::SceneNode * AddObjectToNode(const Ogre::String&strParentNodeName, const Ogre::String&strNodeName, const Ogre::String&strObjName, const Ogre::String&strMatName, const MeshData& data);
	
		void RemoveNodeData(const Ogre::String&strNodeName, const Ogre::String&strObjName = "");

		Ogre::SceneManager::SceneNodeList  CreateOrGetNode(const Ogre::String&strParentNodeName, const Ogre::String&strNodeName);

		void SetCameraPos(const Ogre::Vector3& pos, const Ogre::Vector3& look);

		void changeMaterialToWire();

		void changeMaterialToPolyon();

		void OffsetObj(const ZMString& objName, const ZMPoint3D& offsetAxis, const ZMReal& fOffsetValue, bool isAbs = true);

		void RotateObj(const ZMString& objName, const ZMPoint3D& pntOrign, const ZMPoint3D& rAxis, const ZMReal& fAngle, bool isAbs = true);

	protected:

		virtual void createLight(void);
		virtual void createCamera(void);
		virtual void createObject(void);
		virtual void createMaterial(void);

		virtual void changeMaterial(const Ogre::String& strMatName, bool isWire);

		Ogre::SceneNode* GetDataNode();

		Ogre::ManualObject *  CreateManualObject(const Ogre::String&strObjName, const Ogre::String&strMatName, const MeshData& data);
	private:
		Ogre::HlmsPbsDatablock *  CreateMaterian(const Ogre::String& strMatName, const float& fRoughness, const Ogre::Vector3& fFresnel, const Ogre::String& strDiff = "", const Ogre::String& strNormal = "", const Ogre::String&strRough = "", const Ogre::String&strSpec = "");
		Ogre::ManualObject * CreateTerrian(const Ogre::String&, const Ogre::String&);
		Ogre::ManualObject * CreateWater(const Ogre::String&, const Ogre::String&);
    };
}

#endif
